package carapace

import (
	
	

	
	
	_shell 
	
)

// InvokedAction is a logical alias for an Action whose (nested) callback was invoked.
type InvokedAction struct {
	action Action
}

func ( InvokedAction) () export.Export {
	return export.Export{Meta: .action.meta, Values: .action.rawValues}
}

// Filter filters given values.
//
//	a := carapace.ActionValues("A", "B", "C").Invoke(c)
//	b := a.Filter([]string{"B"}) // ["A", "C"]
func ( InvokedAction) ( ...string) InvokedAction {
	.action.rawValues = .action.rawValues.Filter(...)
	return 
}

// Merge merges InvokedActions (existing values are overwritten)
//
//	a := carapace.ActionValues("A", "B").Invoke(c)
//	b := carapace.ActionValues("B", "C").Invoke(c)
//	c := a.Merge(b) // ["A", "B", "C"]
func ( InvokedAction) ( ...InvokedAction) InvokedAction {
	for ,  := range append([]InvokedAction{}, ...) {
		.action.rawValues = append(.action.rawValues, .action.rawValues...)
		.action.meta.Merge(.action.meta)
	}
	.action.rawValues = .action.rawValues.Unique()
	return 
}

// Prefix adds a prefix to values (only the ones inserted, not the display values)
//
//	carapace.ActionValues("melon", "drop", "fall").Invoke(c).Prefix("water")
func ( InvokedAction) ( string) InvokedAction {
	for ,  := range .action.rawValues {
		.action.rawValues[].Value =  + .Value
	}
	return 
}

// Retain retains given values.
//
//	a := carapace.ActionValues("A", "B", "C").Invoke(c)
//	b := a.Retain([]string{"A", "C"}) // ["A", "C"]
func ( InvokedAction) ( ...string) InvokedAction {
	.action.rawValues = .action.rawValues.Retain(...)
	return 
}

// Suffix adds a suffx to values (only the ones inserted, not the display values)
//
//	carapace.ActionValues("apple", "melon", "orange").Invoke(c).Suffix("juice")
func ( InvokedAction) ( string) InvokedAction {
	for ,  := range .action.rawValues {
		.action.rawValues[].Value = .Value + 
	}
	return 
}

// UidF TODO experimental
func ( InvokedAction) ( func( string) (*url.URL, error)) InvokedAction {
	for ,  := range .action.rawValues {
		,  := (.Value)
		if  != nil {
			return ActionMessage(.Error()).Invoke(Context{})
		}
		.action.rawValues[].Uid = .String()
	}
	return 
}

// ToA casts an InvokedAction to Action.
func ( InvokedAction) () Action {
	return .action
}

func tokenize( string,  ...string) []string {
	if len() == 0 {
		return []string{}
	}

	 := make([]string, 0)
	for ,  := range strings.SplitAfter(, [0]) {
		 := (strings.TrimSuffix(, [0]), [1:]...)
		if len() > 0 && strings.HasSuffix(, [0]) {
			[len()-1] = [len()-1] + [0]
		}
		 = append(, ...)
	}
	return 
}

// ToMultiPartsA create an ActionMultiParts from values with given dividers
//
//	a := carapace.ActionValues("A/B/C", "A/C", "B/C", "C").Invoke(c)
//	b := a.ToMultiPartsA("/") // completes segments separately (first one is ["A/", "B/", "C"])
func ( InvokedAction) ( ...string) Action {
	return ActionCallback(func( Context) Action {
		 := tokenize(.Value, ...)

		 := make(map[string]common.RawValue)
		for ,  := range .action.rawValues {
			if match.HasPrefix(.Value, .Value) {
				if  := tokenize(.Value, ...); len() >= len() {
					 := strings.Join([:len()], "")
					 := [len()-1]

					if len() == len() {
						[] = common.RawValue{
							Value:       ,
							Display:     ,
							Description: .Description,
							Style:       .Style,
							Tag:         .Tag,
							Uid:         .Uid,
						}
					} else {
						[] = common.RawValue{
							Value:       ,
							Display:     ,
							Description: "",
							Style:       "",
							Tag:         .Tag,
							Uid:         .Uid,
						}
					}
				}
			}
		}

		 := make([]common.RawValue, 0)
		for ,  := range  {
			 = append(, )
		}

		 := Action{rawValues: }
		for ,  := range  {
			if  := []rune(); len() == 0 {
				.meta.Nospace.Add('*')
				break
			} else {
				.meta.Nospace.Add([len()-1])
			}
		}
		return 
	})
}

func ( InvokedAction) ( string,  string) string {
	return _shell.Value(, , .action.meta, .action.rawValues)
}

func init() {
	common.FromInvokedAction = func( interface{}) (common.Meta, common.RawValues) {
		if ,  := .(InvokedAction);  {
			return .action.meta, .action.rawValues
		}
		return common.Meta{}, nil
	}
}